#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdarg.h>
#include <pthread.h>
#include <QtGui/QApplication>
#include <QtCore/QFile>
#include <QtCore/QTextStream>
#include <sys/types.h>
#include <sys/ioctl.h>
#include <errno.h>
#include <net/if.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>

#include "mainui.h"
#include "iot_import.h"
#include "iot_export.h"
#include "cJSON.h"
#include "rs232.h"

#define PRODUCT_KEY             "oRdu9fLIToY"
#define DEVICE_NAME             "662429"
#define DEVICE_SECRET           "NmxqwtPmrBFwpAiKGjXt0W8w0Ah3SSk5"


/* These are pre-defined topics */
#define TOPIC_UPDATE            "/"PRODUCT_KEY"/"DEVICE_NAME"/update"
#define TOPIC_GET               "/"PRODUCT_KEY"/"DEVICE_NAME"/get"
#define TOPIC_REPLY             "/"PRODUCT_KEY"/"DEVICE_NAME"/reply"

#define MQTT_MSGLEN             (1024)

#define EXAMPLE_TRACE(fmt, ...)  \
    do { \
        HAL_Printf("%s|%03d :: ", __func__, __LINE__); \
        HAL_Printf(fmt, ##__VA_ARGS__); \
        HAL_Printf("%s", "\r\n"); \
    } while(0)

int init_serial_communication();
void * mqtt_client(void *arg);
int update_publish(char* requestId, char* header, char* operationCode, char* data, char* topicName);
extern int FtpGet(char *host,char *user,char *pass,char *filename,char *pcSaveFile);

struct data_packet
{
    int head;
    int operation;
    unsigned char data[256];
    int data_sz;
};

struct ethtool_value {
    __uint32_t      cmd;
    __uint32_t      data;
};

static const uint8_t aucCRCHi[] = { 
    0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41,
    0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40,
    0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41,
    0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,
    0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41,
    0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40,
    0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40,
    0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40,
    0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41,
    0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40,
    0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41,
    0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 
    0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41,
    0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 
    0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,
    0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,
    0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 
    0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40,
    0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41,
    0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,
    0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41,
    0x00, 0xC1, 0x81, 0x40
}; 

static const uint8_t aucCRCLo[] = {
    0x00, 0xC0, 0xC1, 0x01, 0xC3, 0x03, 0x02, 0xC2, 0xC6, 0x06, 0x07, 0xC7,
    0x05, 0xC5, 0xC4, 0x04, 0xCC, 0x0C, 0x0D, 0xCD, 0x0F, 0xCF, 0xCE, 0x0E,
    0x0A, 0xCA, 0xCB, 0x0B, 0xC9, 0x09, 0x08, 0xC8, 0xD8, 0x18, 0x19, 0xD9,
    0x1B, 0xDB, 0xDA, 0x1A, 0x1E, 0xDE, 0xDF, 0x1F, 0xDD, 0x1D, 0x1C, 0xDC,
    0x14, 0xD4, 0xD5, 0x15, 0xD7, 0x17, 0x16, 0xD6, 0xD2, 0x12, 0x13, 0xD3,
    0x11, 0xD1, 0xD0, 0x10, 0xF0, 0x30, 0x31, 0xF1, 0x33, 0xF3, 0xF2, 0x32,
    0x36, 0xF6, 0xF7, 0x37, 0xF5, 0x35, 0x34, 0xF4, 0x3C, 0xFC, 0xFD, 0x3D,
    0xFF, 0x3F, 0x3E, 0xFE, 0xFA, 0x3A, 0x3B, 0xFB, 0x39, 0xF9, 0xF8, 0x38, 
    0x28, 0xE8, 0xE9, 0x29, 0xEB, 0x2B, 0x2A, 0xEA, 0xEE, 0x2E, 0x2F, 0xEF,
    0x2D, 0xED, 0xEC, 0x2C, 0xE4, 0x24, 0x25, 0xE5, 0x27, 0xE7, 0xE6, 0x26,
    0x22, 0xE2, 0xE3, 0x23, 0xE1, 0x21, 0x20, 0xE0, 0xA0, 0x60, 0x61, 0xA1,
    0x63, 0xA3, 0xA2, 0x62, 0x66, 0xA6, 0xA7, 0x67, 0xA5, 0x65, 0x64, 0xA4,
    0x6C, 0xAC, 0xAD, 0x6D, 0xAF, 0x6F, 0x6E, 0xAE, 0xAA, 0x6A, 0x6B, 0xAB, 
    0x69, 0xA9, 0xA8, 0x68, 0x78, 0xB8, 0xB9, 0x79, 0xBB, 0x7B, 0x7A, 0xBA,
    0xBE, 0x7E, 0x7F, 0xBF, 0x7D, 0xBD, 0xBC, 0x7C, 0xB4, 0x74, 0x75, 0xB5,
    0x77, 0xB7, 0xB6, 0x76, 0x72, 0xB2, 0xB3, 0x73, 0xB1, 0x71, 0x70, 0xB0,
    0x50, 0x90, 0x91, 0x51, 0x93, 0x53, 0x52, 0x92, 0x96, 0x56, 0x57, 0x97,
    0x55, 0x95, 0x94, 0x54, 0x9C, 0x5C, 0x5D, 0x9D, 0x5F, 0x9F, 0x9E, 0x5E,
    0x5A, 0x9A, 0x9B, 0x5B, 0x99, 0x59, 0x58, 0x98, 0x88, 0x48, 0x49, 0x89,
    0x4B, 0x8B, 0x8A, 0x4A, 0x4E, 0x8E, 0x8F, 0x4F, 0x8D, 0x4D, 0x4C, 0x8C,
    0x44, 0x84, 0x85, 0x45, 0x87, 0x47, 0x46, 0x86, 0x82, 0x42, 0x43, 0x83,
    0x41, 0x81, 0x80, 0x40
};

static int      user_argc;
static char     **user_argv;
mainUi          *g_mainUi = 0;
unsigned char   loopbyte[4096];
void            *pclient = 0;
int             iRunning = 0;
int             iMachine = 0;
int             iLoc = 0;
int             iAnalyzeLoc = 0;
int             iLastNet = 0;
int             iCurrentNet = 0;
//int             iHead = 0x39;
int             iHead = 0x02;
//int             cport_nr = 16;      /* /dev/ttyUSB0 */
int             cport_nr = 1;      /* /dev/ttyS2 */
int             currentmachineMode = 0x01;//Ready mode
int             lastMachineMode = -1;
int             machineModeSwitch = 0;

int linkStatusCheck(const char* ethName)
{
    struct ethtool_value edata;
    int fd = -1, err = 0, ret = -1;
    struct ifreq ifr;
  
    memset(&ifr, 0, sizeof(ifr));
    strcpy(ifr.ifr_name, ethName);
    fd = socket(AF_INET, SOCK_DGRAM, 0);
    if (fd < 0) {
        perror("Cannot get control socket");
        return ret;
    }
    edata.cmd = 0x0000000a;
    ifr.ifr_data = (caddr_t)&edata;
    err = ioctl(fd, 0x8946, &ifr);
    if (err == 0) {
        //fprintf(stdout, "Link detected: %s/n", edata.data ? "yes":"no");
        ret = (int)edata.data;
    } else if (errno != EOPNOTSUPP) {
        perror("Cannot get link status");
    }
   return ret;
}

char* random_requestId()
{
    char *requestId = new char[23];
    srand(unsigned(time(0)));

    sprintf(requestId, "%02X %02X %02X %02X %02X %02X %02X %02X",
        rand() % 255,rand() % 255,rand() % 255,rand() % 255,
        rand() % 255,rand() % 255,rand() % 255,rand() % 255);
    return requestId;
}

unsigned char BCC_CheckSum(unsigned char *buf, int len)
{
    unsigned char i;
    unsigned char checksum = 0;

    for(i = 0; i < len; i++) {
        checksum ^= *buf++;
    }

    return checksum;
}

uint16_t usMBCRC16( uint8_t* pucFrame, uint16_t usLen )
{
    uint8_t ucCRCHi = 0xFF;
    uint8_t ucCRCLo = 0xFF;
    int iIndex;
    while( usLen-- )
    {
        iIndex = ucCRCLo ^ *( pucFrame++ );
        ucCRCLo = ( uint8_t )( ucCRCHi ^ aucCRCHi[iIndex] );
        ucCRCHi = aucCRCLo[iIndex];
    } 
    return ( uint16_t )( ucCRCHi << 8 | ucCRCLo );
}

int strsplit(const char *str, char *parts[], const char *delimiter) {
    char *pch;
    int i = 0, j = 0;
    char *copy = NULL, *tmp = NULL;

    copy = strdup(str);
    if (! copy)
    goto bad;

    pch = strtok(copy, delimiter);

    tmp = strdup(pch);
    if (! tmp)
    goto bad;

    parts[i++] = tmp;

    while (pch) {
        pch = strtok(NULL, delimiter);
        if (NULL == pch) break;

        tmp = strdup(pch);
        if (! tmp)
            goto bad;

        parts[i++] = tmp;
    }

    free(copy);
    return i;

    bad:
        free(copy);
        for (j = 0; j < i; j++)
            free(parts[j]);
        return -1;
}

void setMachineMode(int mode)
{
    printf("mode is %d\n", mode);
    switch(mode)
    {
        case 0x01:
            g_mainUi->setStatus("Ready               ");
            break;
        case 0x02:
            g_mainUi->setStatus("Partial vend        ");
            break;
        case 0x04:
            g_mainUi->setStatus("Start               ");
            break;
        case 0x05:
            g_mainUi->setStatus("Start after PF      ");
            break;
        case 0x80:
            g_mainUi->setStatus("Error               ");
            break;
        case 0x08:
            g_mainUi->setStatus("Run                 ");
            break;
        case 0x09:
            g_mainUi->setStatus("Door Lock           ");
            break;
        case 0x0A:
            g_mainUi->setStatus("Door Un-Lock        ");
            break;
        case 0x0B:
            g_mainUi->setStatus("Pause               ");
            break;
        case 0x0C:
            g_mainUi->setStatus("End of Cycle        ");
            break;
        default:
            g_mainUi->setStatus("Unknown             ");
            break;
    }
}

void *serialdata_handle(void *arg)
{
    unsigned char sndBuf[256] = {0};
    int noDataTimes = 0;
    while(iMachine)
    {
        //read
        memset(sndBuf,0,256);
        int isz = RS232_PollComport(cport_nr,sndBuf,256), i = 0 , j = 0;
        if (isz > 0)
        {
            // for(i = 0; i<isz; i++)
            // {
            //    printf("%x ", (int)sndBuf[i]);
            // }
            memcpy(loopbyte+iLoc,sndBuf,isz);
            iLoc += isz;
            noDataTimes = 0;
            //printf("size is %d %d\n", isz, iLoc);
        }
        else
        {
            noDataTimes++;
        }
        //No response within 2 seconds
        if (noDataTimes > 20)
        {
            RS232_CloseComport(cport_nr);
            init_serial_communication();
            noDataTimes = 0;
        }

        //analyze speed queen data
        for(j=iAnalyzeLoc; j<iLoc;j++)
        {
            // if (loopbyte[j] == iHead && j >= 1)
            // {
            //     printf("ACK response %d\n", (int)loopbyte[j-1]);
            // }
            if(loopbyte[j] == iHead && j+1<iLoc)
            {
                int packetsz = loopbyte[j+1];

                //data already can parse to one packet
                if(j+packetsz+2<iLoc)
                {
                    int operationcode = loopbyte[j+2];
                    struct data_packet dp;
                    dp.head = iHead;
                    dp.operation = operationcode;
                    dp.data_sz = packetsz;
                    memcpy((void*)dp.data,(void*)&loopbyte[j+3],packetsz);
                    int ibfsz = j+packetsz+3;
                    // for(int k=0; k<packetsz; k++)
                    // {
                    //     printf("%x\n", dp.data[k]);
                    // }
                    if(ibfsz == iLoc)
                    {
                        //printf("one packet %d\n",dp.data_sz);
                        //reinit every thing
                        if (dp.operation == 0x71)
                        {
                            currentmachineMode = (int)dp.data[4];
                            if (currentmachineMode != lastMachineMode || lastMachineMode == -1)
                            {
                                setMachineMode(currentmachineMode);
                                if (lastMachineMode != -1)
                                {
                                    machineModeSwitch = 1;
                                }
                                lastMachineMode = currentmachineMode;
                            }
                            
                        }
                        iAnalyzeLoc = iLoc = 0;
                        RS232_SendByte(cport_nr,0x06);
                    }
                    else if (ibfsz < iLoc)
                    {
                        if (dp.operation == 0x71)
                        {
                            currentmachineMode = (int)dp.data[4];
                            if (currentmachineMode != lastMachineMode || lastMachineMode == -1)
                            {
                                setMachineMode(currentmachineMode);
                                if (lastMachineMode != -1)
                                {
                                    machineModeSwitch = 1;
                                }
                                lastMachineMode = currentmachineMode;
                                
                            }
                        }
                        memcpy((void*)loopbyte,(void*)&loopbyte[ibfsz],iLoc-ibfsz);
                        //printf("one packet %d\n",dp.data_sz);
                        //reinit every thing
                        iAnalyzeLoc = 0;
                        iLoc = iLoc-ibfsz;
                        RS232_SendByte(cport_nr,0x06);
                    }
                    else
                    {
                        printf("some bad thing happen!!\n");
                    }
                }
                //no enough data, break to next loop
                else
                {
                    iAnalyzeLoc = j;
                    break;
                }
            }
        }
#if 0
        //analyze normal data
        for(j=iAnalyzeLoc; j<iLoc;j++)
        {
            if(loopbyte[j] == iHead && j+1<iLoc)
            {
                int packetsz = loopbyte[j+1];
                //data already can parse to one packet
                if(j+packetsz+3<iLoc)
                {
                    int operationcode = loopbyte[j+2];
                    struct data_packet dp;
                    dp.head = iHead;
                    dp.operation = operationcode;
                    dp.data_sz = packetsz-1;
                    memcpy((void*)dp.data,(void*)loopbyte[j+3],packetsz-1);
                    if(j+packetsz+3 == iLoc -1)
                    {
                        //reinit every thing
                        iAnalyzeLoc = iLoc = 0;
                    }
                    else
                    {
                        memcpy((void*)loopbyte,(void*)loopbyte[j+packetsz+3],iLoc-j-packetsz-4);
                        printf("one packet %d\n",dp.data_sz);
                        //reinit every thing
                        iAnalyzeLoc = 0;
                        iLoc = iLoc-j-packetsz-4;
                    }
                }
                //not enough data, break to next loop
                else
                {
                    iAnalyzeLoc = j;
                    break;
                }
            }
        }
#endif
        //sleep for 300ms
        HAL_SleepMs(300);
    }
}

void *normal_handle(void *arg)
{
    pthread_t *tid1=(pthread_t*)(arg);
    int ret = pthread_equal(*tid1,pthread_self());
    printf("in thread1 tid = %lu, ret is %d\r\n",(unsigned long)pthread_self(),ret);
    //
    unsigned char sndBuf[256] = {0};
    int m = -1;
    sndBuf[++m] = 0x39;
    sndBuf[++m] = 0x01;
    sndBuf[++m] = 0xA1;
    uint16_t crc = usMBCRC16(sndBuf,m+1);
    sndBuf[++m] = crc >> 8;
    sndBuf[++m] = crc & 0xFF;
    while(iMachine)
    {
        //send status request
        RS232_SendBuf(cport_nr,sndBuf,m+1);
        usleep(3000*1000);
    }
    return ((void*)2);
}

void *speedqueen_handle(void *arg)
{
    pthread_t *tid1=(pthread_t*)(arg);
    int ret = pthread_equal(*tid1,pthread_self());
    printf("in thread1 tid = %lu, ret is %d\r\n",(unsigned long)pthread_self(),ret);
    //
    unsigned char sndBuf[256] = {0};
    //send status request
    int m = -1;
    sndBuf[++m] = 0x02;
    sndBuf[++m] = 0x01;
    sndBuf[++m] = 0x70;
    sndBuf[++m] = BCC_CheckSum(sndBuf,m);
    while(iMachine)
    {
        //write
        RS232_SendBuf(cport_nr,sndBuf,m+1);
        usleep(300*1000);    
    }
    return ((void*)2);
}

void event_handle(void *pcontext, void *pclient, iotx_mqtt_event_msg_pt msg)
{
    uintptr_t packet_id = (uintptr_t)msg->msg;
    iotx_mqtt_topic_info_pt topic_info = (iotx_mqtt_topic_info_pt)msg->msg;

    switch (msg->event_type) {
        case IOTX_MQTT_EVENT_UNDEF:
            EXAMPLE_TRACE("undefined event occur.");
            break;

        case IOTX_MQTT_EVENT_DISCONNECT:
            EXAMPLE_TRACE("MQTT disconnect.");
            break;

        case IOTX_MQTT_EVENT_RECONNECT:
            EXAMPLE_TRACE("MQTT reconnect.");
            break;

        case IOTX_MQTT_EVENT_SUBCRIBE_SUCCESS:
            EXAMPLE_TRACE("subscribe success, packet-id=%u", (unsigned int)packet_id);
            break;

        case IOTX_MQTT_EVENT_SUBCRIBE_TIMEOUT:
            EXAMPLE_TRACE("subscribe wait ack timeout, packet-id=%u", (unsigned int)packet_id);
            break;

        case IOTX_MQTT_EVENT_SUBCRIBE_NACK:
            EXAMPLE_TRACE("subscribe nack, packet-id=%u", (unsigned int)packet_id);
            break;

        case IOTX_MQTT_EVENT_UNSUBCRIBE_SUCCESS:
            EXAMPLE_TRACE("unsubscribe success, packet-id=%u", (unsigned int)packet_id);
            break;

        case IOTX_MQTT_EVENT_UNSUBCRIBE_TIMEOUT:
            EXAMPLE_TRACE("unsubscribe timeout, packet-id=%u", (unsigned int)packet_id);
            break;

        case IOTX_MQTT_EVENT_UNSUBCRIBE_NACK:
            EXAMPLE_TRACE("unsubscribe nack, packet-id=%u", (unsigned int)packet_id);
            break;

        case IOTX_MQTT_EVENT_PUBLISH_SUCCESS:
            EXAMPLE_TRACE("publish success, packet-id=%u", (unsigned int)packet_id);
            break;

        case IOTX_MQTT_EVENT_PUBLISH_TIMEOUT:
            EXAMPLE_TRACE("publish timeout, packet-id=%u", (unsigned int)packet_id);
            break;

        case IOTX_MQTT_EVENT_PUBLISH_NACK:
            EXAMPLE_TRACE("publish nack, packet-id=%u", (unsigned int)packet_id);
            break;

        case IOTX_MQTT_EVENT_PUBLISH_RECVEIVED:
            EXAMPLE_TRACE("topic message arrived but without any related handle: topic=%.*s, topic_msg=%.*s",
                          topic_info->topic_len,
                          topic_info->ptopic,
                          topic_info->payload_len,
                          topic_info->payload);
            break;

        case IOTX_MQTT_EVENT_BUFFER_OVERFLOW:
            EXAMPLE_TRACE("buffer overflow, %s", msg->msg);
            break;

        default:
            EXAMPLE_TRACE("Should NOT arrive here.");
            break;
    }
}

void operation_normal(int head, int operation, char* data)
{
    unsigned char sndBuf[256] = {0};
    int m = -1;
    sndBuf[++m] = head;
    if (strlen(data) > 0)
    {
        char *parts[128] = {NULL};
        size_t size = strsplit(data, parts, " ");
        int i = 0;
        sndBuf[++m] = 0x01+size;
        sndBuf[++m] = operation;
        for (; i < (int) size; ++i) {
            sndBuf[++m] = strtol(parts[i], 0, 16);
            free(parts[i]);
        }
    }
    else
    {
        sndBuf[++m] = 0x01;
        sndBuf[++m] = operation;
    }
    uint16_t crc = usMBCRC16(sndBuf,m+1);
    sndBuf[++m] = crc >> 8;
    sndBuf[++m] = crc & 0xFF;
    //write
    RS232_SendBuf(cport_nr,sndBuf,m+1);
}

void operation_speedqueen(int head, int operation, char* data)
{
    unsigned char sndBuf[256] = {0};
    int m = -1;
    sndBuf[++m] = head;
    if (strlen(data) > 0)
    {
        char *parts[128] = {NULL};
        size_t size = strsplit(data, parts, " ");
        int i = 0;
        sndBuf[++m] = size + 1;
        sndBuf[++m] = operation;
        for (; i < (int) size; ++i) {
            sndBuf[++m] = strtol(parts[i], 0, 16);
            free(parts[i]);
        }
    }
    else
    {
        sndBuf[++m] = 0x01;
        sndBuf[++m] = operation;
    }
    sndBuf[++m] = BCC_CheckSum(sndBuf,m);
    //write
    int lp = 0;
    for (lp=0;lp<m+1;lp++)
    {
        printf("%x ",sndBuf[lp]);
    }
    RS232_SendBuf(cport_nr,sndBuf,m+1);
    HAL_SleepMs(300);
    RS232_SendByte(cport_nr,0x06);
}

int update_publish(char* requestId, char* header, char* operationCode, char* data, char* topicName)
{
    iotx_mqtt_topic_info_t topic_msg;
    char msg_pub[256];
    memset(msg_pub,0,256);
    /* Initialize topic information */
    memset(&topic_msg, 0x0, sizeof(iotx_mqtt_topic_info_t));
    sprintf(msg_pub, "{\"RequestId\":\"%s\",\"OperationCode\":\"%s\",\"Header\":\"%s\",\"Data\":\"%s \"}",requestId,operationCode,header,data);
    printf("pub data is %s\n",msg_pub);
    topic_msg.qos = IOTX_MQTT_QOS1;
    topic_msg.retain = 0;
    topic_msg.dup = 0;
    topic_msg.payload = msg_pub;
    topic_msg.payload_len = strlen(msg_pub);

    int rc = IOT_MQTT_Publish(pclient, topicName, &topic_msg);
    EXAMPLE_TRACE("rc = IOT_MQTT_Publish() = %d", rc);
    return rc;
}

int mqtt_publish(char* requestId, char* header, char* operationCode, char* data, const char* topicName)
{
    iotx_mqtt_topic_info_t topic_msg;
    char msg_pub[256];
    memset(msg_pub,0,256);
    /* Initialize topic information */
    memset(&topic_msg, 0x0, sizeof(iotx_mqtt_topic_info_t));
    char reportdata[256] = {0};
    //update OTA
    if(strcmp(operationCode, "90") == 0)
    {
        strcpy(reportdata,"1");
    }
    //response query
    else if(strcmp(operationCode, "AA") == 0)
    {
        strcpy(reportdata,"");
    }
    //number group update
    else if(strcmp(operationCode, "94") == 0)
    {
        strcpy(reportdata,"");
    }
    //keyboard lock
    else if(strcmp(operationCode, "95") == 0)
    {
        strcpy(reportdata,"");
    }
    //factory mode test
    else if(strcmp(operationCode, "96") == 0)
    {
        strcpy(reportdata,"");
    }
    //signal check
    else if(strcmp(operationCode, "AB") == 0)
    {
        strcpy(reportdata,"1,Sig:17,Ber:99");
    }
    //sim ccid query
    else if(strcmp(operationCode, "AC") == 0)
    {
        strcpy(reportdata,"1, DevSn: 600007,CCID: 89860002190810001367");
    }
    else if(strcmp(operationCode, "81") == 0)
    {
        //strcpy(reportdata,"1, DevSn: 600007,CCID: 89860002190810001367");
        printf("Reveive 81 now for test\n");
        operation_speedqueen(0x02,0x6A,"05 00 00 00 00");
        HAL_SleepMs(200);
        //retry if the mode not change
        while (currentmachineMode != 0x04)
        {
            operation_speedqueen(0x02,0x6A,"05 00 00 00 00");
            HAL_SleepMs(800);
        }
        operationCode = "C0";
        strcpy(reportdata,"81");

        update_publish(requestId, header, "81", "F0", TOPIC_REPLY);
    }
    else if(strcmp(operationCode, "1A") == 0)
    {
        char cmd[128] = {0};
        sprintf(cmd,"echo %s > /root/qrcode",data);
        system(cmd);
        if (0 != g_mainUi)
        {
            g_mainUi->updateQrCodeContent(data);
        }
        strcpy(reportdata,"1");
    }
    else if(strcmp(operationCode, "2A") == 0)
    {
        char cmd[128] = {0};
        sprintf(cmd,"echo %s > /root/telphone",data);
        system(cmd);
        if (0 != g_mainUi)
        {
            char telphone[128] = {0};
            sprintf(telphone,"MACHINE: 662429          TEL: %s",data);
            g_mainUi->setInfo(telphone);
        }
        strcpy(reportdata,"1");
    }
    else
    {
        //operation on the machine
        #if 0
        int ihead = strtol(header,0,16);
        int ioperation = strtol(operationCode,0,16);
        printf("machine op ==== %d %d\n", ihead, ioperation);
        char *parts[128] = {NULL};
        if (strstr(data,"|") != 0)
        {
            size_t size = strsplit(data, parts, "|");
            if (size > 0)
            {
                operation_normal(ihead,ioperation,parts[0]);
                int i=0;
                for(i=0;i<size;i++)
                {
                    free(parts[i]);
                }
            }
        }
        else
        {
            operation_normal(ihead,ioperation,data);
        }
        #endif
        operationCode = "C0";
    }
    // //obtain number group
    // else if(strcmp(operationCode, "92") == 0)
    // {

    // }
    // //report device status
    // else if(strcmp(operationCode, "A1") == 0)
    // {

    // }
    // //network watch dog
    // else if(strcmp(operationCode, "A9") == 0)
    // {

    // }
    sprintf(msg_pub, "{\"RequestId\":\"%s\",\"OperationCode\":\"%s\",\"Header\":\"%s\",\"Data\":\"%s \"}",requestId,operationCode,header,reportdata);
    printf("pub data is %s\n",msg_pub);
    topic_msg.qos = IOTX_MQTT_QOS1;
    topic_msg.retain = 0;
    topic_msg.dup = 0;
    topic_msg.payload = msg_pub;
    topic_msg.payload_len = strlen(msg_pub);

    int rc = IOT_MQTT_Publish(pclient, topicName, &topic_msg);
    EXAMPLE_TRACE("rc = IOT_MQTT_Publish() = %d", rc);

    return rc;
}

/* main logic for network*/
static void logic_handler(void *pcontext, void *pclient, iotx_mqtt_event_msg_pt msg)
{
    iotx_mqtt_topic_info_pt ptopic_info = (iotx_mqtt_topic_info_pt) msg->msg;

    /* print topic name and topic message */
    EXAMPLE_TRACE("----");
    EXAMPLE_TRACE("Topic: '%.*s' (Length: %d)",
                  ptopic_info->topic_len,
                  ptopic_info->ptopic,
                  ptopic_info->topic_len);
    EXAMPLE_TRACE("Payload: '%.*s' (Length: %d)",
                  ptopic_info->payload_len,
                  ptopic_info->payload,
                  ptopic_info->payload_len);
    EXAMPLE_TRACE("----");
    /* parse payload */
    #if 0
    iotx_mqtt_topic_info_t topic_msg;
    char msg_pub[256];
    memset(msg_pub,0,256);
    /* Initialize topic information */
    memset(&topic_msg, 0x0, sizeof(iotx_mqtt_topic_info_t));
    topic_msg.qos = IOTX_MQTT_QOS1;
    topic_msg.retain = 0;
    topic_msg.dup = 0;
    topic_msg.payload = ptopic_info->payload;
    topic_msg.payload_len = ptopic_info->payload_len;

    int rc = IOT_MQTT_Publish(pclient, TOPIC_REPLY, &topic_msg);
    EXAMPLE_TRACE("rc = IOT_MQTT_Publish() = %d", rc);
    #endif
    
    cJSON *jsonroot = cJSON_Parse(ptopic_info->payload);
    if (0 != jsonroot)
    {
        //publish the reply
        mqtt_publish(cJSON_GetObjectItem(jsonroot, "RequestId")->valuestring
            ,cJSON_GetObjectItem(jsonroot, "Header")->valuestring
            ,cJSON_GetObjectItem(jsonroot, "OperationCode")->valuestring
            ,cJSON_GetObjectItem(jsonroot, "Data")->valuestring,TOPIC_REPLY);
    }
    
    
}

void init_network()
{
    //check link status
    int iLinkZero = linkStatusCheck("eth0");
    int iLinkOne = linkStatusCheck("eth1");
    while (iLinkZero != 1 && iLinkOne != 1)
    {
        //power off the 4g
        system("echo 0 > /sys/class/gpio_sw/PH9/data");
        HAL_SleepMs(500);
        system("echo 1 > /sys/class/gpio_sw/PH9/data");
        HAL_SleepMs(500);
        //init the network
        system("udhcpc -i eth0 -s /usr/share/udhcpc/default.script -n");
        HAL_SleepMs(500);
        system("udhcpc -i eth1 -s /usr/share/udhcpc/default.script -n");
        iLinkZero = linkStatusCheck("eth0");
        iLinkOne = linkStatusCheck("eth1");
        //connected
        if (iLinkZero == 1 || iLinkOne == 1)
            break;
        HAL_SleepMs(20000);
    }

}

void reinit_network()
{
    pthread_t tid1;
    //start the mqtt network
    //IOT_OpenLog("mqtt");
    //IOT_SetLogLevel(IOT_LOG_DEBUG);
    int ret = pthread_create(&tid1,NULL,mqtt_client,&tid1);
}

void * mqtt_client(void *arg)
{
    HAL_SleepMs(1000);
    init_network();

    int isz = FtpGet("wmlsxq.oicp.io","xcdz","xc5588","machine/snkey","snkey");
    printf("output file size is %d\n", isz);
    //will out if we not get that file
    if (isz != 5)
    {
        return 0;
    }
    int rc = 0, msg_len, cnt = 0, iLoopTimes = 0;

    iotx_conn_info_pt pconn_info;
    iotx_mqtt_param_t mqtt_params;

    char *msg_buf = NULL, *msg_readbuf = NULL;

    if (NULL == (msg_buf = (char *)HAL_Malloc(MQTT_MSGLEN))) {
        EXAMPLE_TRACE("not enough memory");
        rc = -1;
        goto do_exit;
    }

    if (NULL == (msg_readbuf = (char *)HAL_Malloc(MQTT_MSGLEN))) {
        EXAMPLE_TRACE("not enough memory");
        rc = -1;
        goto do_exit;
    }

    /* Device AUTH */
    if (0 != IOT_SetupConnInfo(PRODUCT_KEY, DEVICE_NAME, DEVICE_SECRET, (void **)&pconn_info)) {
        EXAMPLE_TRACE("AUTH request failed!");
        rc = -1;
        goto do_exit;
    }

    /* Initialize MQTT parameter */
    memset(&mqtt_params, 0x0, sizeof(mqtt_params));

    mqtt_params.port = pconn_info->port;
    mqtt_params.host = pconn_info->host_name;
    mqtt_params.client_id = pconn_info->client_id;
    mqtt_params.username = pconn_info->username;
    mqtt_params.password = pconn_info->password;
    mqtt_params.pub_key = pconn_info->pub_key;

    mqtt_params.request_timeout_ms = 2000;
    mqtt_params.clean_session = 0;
    mqtt_params.keepalive_interval_ms = 5000;
    mqtt_params.pread_buf = msg_readbuf;
    mqtt_params.read_buf_size = MQTT_MSGLEN;
    mqtt_params.pwrite_buf = msg_buf;
    mqtt_params.write_buf_size = MQTT_MSGLEN;

    mqtt_params.handle_event.h_fp = event_handle;
    mqtt_params.handle_event.pcontext = NULL;


    /* Construct a MQTT client with specify parameter */
    pclient = IOT_MQTT_Construct(&mqtt_params);
    if (NULL == pclient) {
        EXAMPLE_TRACE("MQTT construct failed");
        rc = -1;
        if (g_mainUi != 0)
        {
            g_mainUi->setNetStatus("0");
        }
        goto do_exit;
    }

    /* Subscribe the specific topic */
    rc = IOT_MQTT_Subscribe(pclient, TOPIC_GET, IOTX_MQTT_QOS1, logic_handler, NULL);
    if (rc < 0) {
        IOT_MQTT_Destroy(&pclient);
        EXAMPLE_TRACE("IOT_MQTT_Subscribe() failed, rc = %d", rc);
        rc = -1;
        goto do_exit;
    }
    if (g_mainUi != 0)
    {
        g_mainUi->setNetStatus("1");
    }
    iRunning = 1; iLastNet = iCurrentNet = 1;
    
    while(iRunning)
    {
        int iStatus = IOT_MQTT_Yield(pclient, 200);
        HAL_SleepMs(2000);
        iLoopTimes++;
        if (0 != machineModeSwitch)
        {
            //Send current status
            char* requestId = random_requestId();
            char data[5] = {0};
            sprintf(data,"%02X",currentmachineMode);
            update_publish(requestId,"42","A1",data,TOPIC_UPDATE);
            delete[] requestId;
            machineModeSwitch = 0;
        }
        if (iLoopTimes > 30)
        {
            //Send current status
            char* requestId = random_requestId();
            char data[5] = {0};
            sprintf(data,"%02X",currentmachineMode);
            update_publish(requestId,"42","A1",data,TOPIC_UPDATE);
            delete[] requestId;
            iLoopTimes = 0;
        }
        //Lost Network
        if (iStatus != 0)
        {
            printf("Can't connect to Aliyun!!! Re init network\n");
            if (g_mainUi != 0)
            {
                g_mainUi->setNetStatus("0");
            }
            iRunning = 0;
            reinit_network();
            break;
            //exit
        }
    }
    
    IOT_MQTT_Unsubscribe(pclient, TOPIC_GET);
    HAL_SleepMs(200);
    IOT_MQTT_Destroy(&pclient);
    IOT_DumpMemoryStats(IOT_LOG_DEBUG);
    IOT_CloseLog();

    EXAMPLE_TRACE("out of sample!");
    
do_exit:
    if (NULL != msg_buf) {
        HAL_Free(msg_buf);
    }

    if (NULL != msg_readbuf) {
        HAL_Free(msg_readbuf);
    }

    //return rc;
}

int initNormal()
{
    int bdrate=9600;                /* 57600 baud */
    char mode[]={'8','N','1',0};    // 8 N 1
    int iRet = 0, m = -1, isz = 0;
    if(RS232_OpenComport(cport_nr, bdrate, mode))
    {
        return iRet;
    }
}

int initSpeedQueen()
{
    int iRet = -1, m = -1, isz = 0, imax = 5, inores = 0;

    //init the communicate sequence
    unsigned char sndBuf[256] = {0};
    sndBuf[++m] = 0x02;
    sndBuf[++m] = 0x09;
    sndBuf[++m] = 0x73;
    sndBuf[++m] = 0x00;
    sndBuf[++m] = 0x00;
    sndBuf[++m] = 0x00;
    sndBuf[++m] = 0x00;
    sndBuf[++m] = 0x00;
    sndBuf[++m] = 0x10;
    sndBuf[++m] = 0x00;
    sndBuf[++m] = 0x00;
    sndBuf[++m] = BCC_CheckSum(sndBuf,m);
    //write
    // int lp = 0;
    // for (lp=0;lp<m+1;lp++)
    // {
    //     printf("%x ",sndBuf[lp]);
    // }
    RS232_SendBuf(cport_nr,sndBuf,m+1);
    //read
    memset(sndBuf,0,256);
    isz = RS232_PollComport(cport_nr,sndBuf,256);
    while(isz<34)
    {
        HAL_SleepMs(300);
        int iappend = RS232_PollComport(cport_nr,sndBuf+isz,256-isz);
        isz += iappend;
        //printf("init comm read sz %d\n",isz);
        inores++;
        if (inores > imax)
        {
            return iRet;
        }
    }
    //send ACK
    RS232_SendByte(cport_nr,0x06);
    //vend init
    m = -1;
    sndBuf[++m] = 0x02;
    sndBuf[++m] = 0x01;
    sndBuf[++m] = 0x70;
    sndBuf[++m] = BCC_CheckSum(sndBuf,m);
    //write
    // for (lp=0;lp<m+1;lp++)
    // {
    //     printf("%x ",sndBuf[lp]);
    // }
    RS232_SendBuf(cport_nr,sndBuf,m+1);
    //read
    memset(sndBuf,0,256);
    isz = RS232_PollComport(cport_nr,sndBuf,256);
    inores = 0;
    while(isz<30)
    {
        HAL_SleepMs(300);
        int iappend = RS232_PollComport(cport_nr,sndBuf+isz,256-isz);
        isz += iappend;
        //printf("init vend read sz %d\n",isz);
        inores++;
        if (inores > imax)
        {
            return iRet;
        }
    }
    //send ACK
    RS232_SendByte(cport_nr,0x06);
    memset(sndBuf,0,256);
    m = -1;
    sndBuf[++m] = 0x02;
    sndBuf[++m] = 10;
    sndBuf[++m] = 0x72;
    sndBuf[++m] = 0x05;
    sndBuf[++m] = 0x00;
    sndBuf[++m] = 0x00;
    sndBuf[++m] = 0x00;
    sndBuf[++m] = 0x00;
    sndBuf[++m] = 0x00;
    sndBuf[++m] = 0x00;
    sndBuf[++m] = 0x00;
    sndBuf[++m] = 0x00;
    sndBuf[++m] = BCC_CheckSum(sndBuf,m);
    //write
    // for (lp=0;lp<m+1;lp++)
    // {
    //     printf("%x ",sndBuf[lp]);
    // }
    RS232_SendBuf(cport_nr,sndBuf,m+1);
    //read ACK
    memset(sndBuf,0,256);
    isz = RS232_PollComport(cport_nr,sndBuf,256);
    inores = 0;
    while(isz<1)
    {
        HAL_SleepMs(300);
        int iappend = RS232_PollComport(cport_nr,sndBuf+isz,256-isz);
        isz += iappend;
        //printf("last ack read sz %d\n",isz);
        inores++;
        if (inores > imax)
        {
            return iRet;
        }
    }
    //end
    return 0;
}

int init_serial_communication()
{
    printf("MQTT inited, now start the serial communication!!!\n");
    int bdrate=9600;                /* 57600 baud */
    char mode[]={'8','N','1',0};    // 8 N 1
    if(RS232_OpenComport(cport_nr, bdrate, mode))
    {
        printf("fatal error to open the com port %d\n", cport_nr);
        return 0;
    }
    int maxrRetry = 3, currentNm = 0, portLoop = 0;
    while(initSpeedQueen() != 0)
    {
        //sleep for 3000 to retry
        HAL_SleepMs(1000);
    }

    printf("Init the Machine successfully, now create the read and operate thread\n");
    return 1;
}

void *init_machine(void *arg)
{
    pthread_t tid1,tid2,tid3,tid4;
    int ret = 0;
    //start the mqtt network
    //IOT_OpenLog("mqtt");
    //IOT_SetLogLevel(IOT_LOG_DEBUG);
    //check file;

    ret = pthread_create(&tid3,NULL,mqtt_client,&tid3);

    //ret = pthread_create(&tid4,NULL,network_check,&tid4);
    //init the serial
    ret = init_serial_communication();
    if (ret != 0)
    {
        iMachine = 1;
        ret = pthread_create(&tid1,NULL,speedqueen_handle,&tid1);
        ret = pthread_create(&tid2,NULL,serialdata_handle,&tid2);
    }
    
}

int main(int argc, char **argv)
{
    QApplication app(argc,argv);
    mainUi mainWin;
    g_mainUi = &mainWin;
    mainWin.setStatus("Initializing......  ");
    QFile telfile("/root/telphone");
    char chrTel[128] = {0};
    char chrQr[256] = {0};
    int fd = open("/root/qrcode",O_RDONLY);
    if (fd != -1)
    {
        int isize = read(fd,chrQr,sizeof(chrQr));
        close(fd);
        printf("read size %d %s\n", isize, chrQr);
        if (isize > 0)
        {
            mainWin.updateQrCodeContent(chrQr);
        }
        else
        {
            mainWin.updateQrCodeContent("wwww.baidu.com");
        }
    }
    else
    {
        mainWin.updateQrCodeContent("wwww.baidu.com");
    }

    fd = open("/root/telphone",O_RDONLY);
    if (fd != -1)
    {
        int isize = read(fd,chrTel,sizeof(chrTel));
        printf("read size %d %s\n", isize, chrTel);
        if (isize > 0)
        {
            char telNum[128] = {0};
            sprintf(telNum,"MACHINE: 662429          TEL: %s",chrTel);
            mainWin.setInfo(telNum);
        }
        else
        {
            mainWin.setInfo("MACHINE: 662429          TEL: 0512-62983027");
        }
        close(fd);
    }
    else
    {
        mainWin.setInfo("MACHINE: 662429          TEL: 0512-62983027");
    }
    
    mainWin.setNetStatus("2");
    mainWin.show();
    //request certificate file
    if (argc >=2)
    {
        printf("arg %d %s\n", argc, argv[1]);
        cport_nr = atoi(argv[1]);
    }
    //create thread
    pthread_t mainThread;
    pthread_create(&mainThread,NULL,init_machine,&mainThread);
    int apprt = app.exec();

    return 0;
}